#ifndef SHIP_H
#define SHIP_H

#include <map>
#include <list>

#include "drawable.h"
#include "updateable.h"
#include "physicsable.h"
#include "spawnable.h"

#include "component.h"

#include "boosters.h"
#include "gun.h"
#include "laser.h"

#include "buttonPress.h"

//NOTE!!! If you see this, tell jeff
//NOTE!!! Make new class of object, the responder, that responds to buttonPresses

//NOTE!!! Reduce the size of the component lists by splitting them into specializations
//NOTE!!! like how the game handles objects... maybe make an object handler type

class Ship : public Drawable, public Updateable, public Physicsable {
    private: 
    float r;
    float g;
    float b;

	float cR;
	float cG;
	float cB;
	
	std::map<char, std::list<Component*>*> keyBinds_;
	std::list<Component*> components_;
	
	cpVect * vertii_;
	int numVertii_;

	cpVect * bridgeVertii_;
	int numBridgeVertii_;

	Ship()
		: Drawable(2),
		  Physicsable() {}
    
    public:
	Ship(float mass)
		: Drawable(2),
		  Physicsable(SHIP, mass) {

		numVertii_ = 6;
		vertii_ = new cpVect[numVertii_];
		vertii_[0].x =   2.0; vertii_[0].y =  20.0;
		vertii_[1].x =  10.0; vertii_[1].y = -10.0;
		vertii_[2].x =   5.0; vertii_[2].y = -15.0;
		vertii_[3].x =  -5.0; vertii_[3].y = -15.0;
		vertii_[4].x = -10.0; vertii_[4].y = -10.0;
		vertii_[5].x =  -2.0; vertii_[5].y =  20.0;

		numBridgeVertii_ = 4;
		bridgeVertii_ = new cpVect[numBridgeVertii_];
		bridgeVertii_[0].x =  1.0; bridgeVertii_[0].y =  9.0;
		bridgeVertii_[1].x =  3.0; bridgeVertii_[1].y = -3.0;
		bridgeVertii_[2].x = -3.0; bridgeVertii_[2].y = -3.0;
		bridgeVertii_[3].x = -1.0; bridgeVertii_[3].y =  9.0;
        
		//Zero mass because we have already set this physicsables mass in the constructor
		addPolyShape(0.0, numVertii_, vertii_, cpvzero);
		
		cpVect laserForce = cpv(0.0, 1300.0);
		Laser* lP; // hahaha, laserPointer... oh c++

		lP = new Laser(getBody(), laserForce, cpv(0.0, 18.0), cpv(0.0, 1.0));
		addComponent(lP);
		bindComponent('c', lP);

		cpVect gunForce = cpv(0.0, 1000.0);
		Gun* gP;

		gP = new Gun(getBody(), gunForce, cpv( 4.0,  10.0), cpv(-0.0, 1.0));
		addComponent(gP);
		bindComponent(' ', gP);

		gP = new Gun(getBody(), gunForce, cpv(-4.0,  10.0), cpv( 0.0, 1.0));
		addComponent(gP);
		bindComponent(' ', gP);

		gP = new Gun(getBody(), gunForce, cpv( 9.0, -10.0), cpv( 0.0, 1.0));
		addComponent(gP);
		bindComponent(' ', gP);

		gP = new Gun(getBody(), gunForce, cpv(-9.0, -10.0), cpv( 0.0, 1.0));
		addComponent(gP);
		bindComponent(' ', gP);
		
		float engineForce = 50.0;
		Boosters* bP;

		bP = new Boosters(getBody(), engineForce, cpv( 5.0, -13.0), cpv( 0.0,  1.0));
		addComponent(bP);
		bindComponent('w', bP);

		bP = new Boosters(getBody(), engineForce, cpv(-5.0, -13.0), cpv( 0.0,  1.0));
		addComponent(bP);
		bindComponent('w', bP);

		bP = new Boosters(getBody(), engineForce, cpv( 1.0,  18.0), cpv(-0.2, -1.0));
		addComponent(bP);
		bindComponent('s', bP);

		bP = new Boosters(getBody(), engineForce, cpv(-1.0,  18.0), cpv( 0.2, -1.0));
		addComponent(bP);
		bindComponent('s', bP);

		bP = new Boosters(getBody(), engineForce, cpv(-5.0,   4.0), cpv( 1.0, -0.2));
		addComponent(bP);
		bindComponent('d', bP);
		bindComponent('x', bP);

		bP = new Boosters(getBody(), engineForce, cpv(-5.0,  -4.0), cpv( 1.0,  0.2));
		addComponent(bP);
		bindComponent('d', bP);
		bindComponent('z', bP);

		bP = new Boosters(getBody(), engineForce, cpv( 5.0,   4.0), cpv(-1.0, -0.2));
		addComponent(bP);
		bindComponent('a', bP);
		bindComponent('z', bP);

		bP = new Boosters(getBody(), engineForce, cpv( 5.0,  -4.0), cpv(-1.0,  0.2));
		addComponent(bP);
		bindComponent('a', bP);
		bindComponent('x', bP);

        r = 0.3;
        g = 0.3;
        b = 0.3;

		cR = 0.5;
		cG = 0.5;
		cB = 0.9;
    }

    void draw();

    void update(float step);

	//Responder functions
	void respond(ButtonPress button);

	//Component functions
	inline void addComponent(Component* component) {
		components_.push_back(component);
	}

	inline void bindComponent(char button, Component* component) {
		if(keyBinds_[button] == NULL) {
			keyBinds_[button] = new std::list<Component*>();
		}		
		keyBinds_[button]->push_back(component);
	}
};

#endif
